#include <iostream>
#include <stdexcept>
#include <string>
#include <fstream>
#include "item.h"
#include "itemfactory.h"
#include "mapitem.h"
#include "mapitemfactory.h"
#include <boost/archive/binary_oarchive.hpp>                               
#include <boost/archive/binary_iarchive.hpp>
using namespace std;

MapItemFactory::MapItemFactory(){
	mapitem_ = 0;
}

MapItemFactory::~MapItemFactory(){
	delete mapitem_;
}

void MapItemFactory::setWalkable(bool walkable){
	mapitem_->setWalkable(walkable);
}

void MapItemFactory::setPortal(bool portal)
{
       mapitem_->setPortal(portal);
}

void MapItemFactory::setItem(bool item)
{
       mapitem_->setItem(item);
}

bool MapItemFactory::getWalkable(){
	return mapitem_->getWalkable();
}

// Create a new mapitem blueprint
void MapItemFactory::create(string id) throw (mapitemfactory_error){

	string itemFile = "adventure2/items/map/" + id + ".add";
	const char* file = itemFile.c_str();
	fstream load(file, ios::in|ios::binary);

	if(!load)
	{
		mapitem_ = new MapItem();

		// Make a connection to our parents item_
		makeConn();

		mapitem_->setId(id);
		//save();
	}
	else
	{
		throw mapitemfactory_error("mapitemfactory: Blueprint does already exist!");
	}
	
	load.close();
	
}

// Creates a mapitem object from a blueprint and returns it
MapItem* MapItemFactory::build(string id) throw(mapitemfactory_error){
	MapItem* item;
	string filename = "adventure2/items/map/" + id + ".add";
	const char* file = filename.c_str();
	fstream load(file, ios::in|ios::binary);
	
	// Load mapitem if the file exists
	if(load)
	{
		ifstream ifs(file);
		boost::archive::binary_iarchive ia(ifs);
		ia >> item;
	}
	else
	{
		throw mapitemfactory_error("mapitemfactory: Could not build mapitem!");
	}	

	return item;
}

// Save changes made to blueprint
void MapItemFactory::save(){
	if(mapitem_ != 0)
	{
		string filename = "adventure2/items/map/" + mapitem_->getId() + ".add";
		const char* file = filename.c_str();
		
		// Clear the file
		fstream savetofile(file, ios::out|ios::binary|ios::trunc);	
		savetofile.close();
		
		// Save the mapitem object
		{
			ofstream ofs(file);
			boost::archive::binary_oarchive oa(ofs);
			oa << mapitem_;
		}
	}
	else
	{
		throw mapitemfactory_error("mapitemfactory: Tried to save a nullpointer!");
	}
	
}

// Load a blueprint
void MapItemFactory::load(string id) throw(mapitemfactory_error){
	// Get path to file
	string filename = "adventure2/items/map/" + id + ".add";
	const char* file = filename.c_str();
	fstream load(file, ios::in|ios::binary);
	
	// Load mapitem if the file exists
	if(load)
	{
	      	MapItem* garbage = mapitem_;
		mapitem_ = 0;
		delete garbage;

		ifstream ifs(file);
		boost::archive::binary_iarchive ia(ifs);
		ia >> mapitem_;

		// Make a connection to our parents item_
		makeConn();
	}
	else
	{
		throw mapitemfactory_error("mapitemfactory: Blueprint does not exist!");
	}
	
	load.close();
}

void MapItemFactory::delItem() throw(mapitemfactory_error)
{
	
	if(mapitem_ != 0)
	{
		// Get the path to the file and delete it
		string filename = "adventure2/items/map/" + mapitem_->getId() + ".add";
		const char* file = filename.c_str();
		remove(file);
		
		// Remove the object we are working with
		MapItem* garbage = mapitem_;
		mapitem_ = 0;
		delete garbage;

	}
	else
	{
		throw mapitemfactory_error("mapitemfactory: Tried to delete a null pointer!");
	}

}

// Make a connection to our parents item_
void MapItemFactory::makeConn()
{
	item_ = (Item*)mapitem_;
}
